package top.jacktgq.lock.deadLock.philosopher.v3;

import java.util.concurrent.locks.ReentrantLock;

import top.jacktgq.utils.LogUtils;
import top.jacktgq.utils.Sleeper;

/**
 * 
 * @Title: PhilosopherEatingProblem.java 
 * @Package top.jacktgq.lock.deadLock 
 * @Description: 哲学家就餐问题：出现循环死锁
 * 					解决办法：采用ReentrantLock进行结果
 * @author CandyWall   
 * @date 2020年11月2日 上午1:08:19 
 * @version V1.0
 */
public class PhilosopherEatingProblem_Solve {
	public static void main(String[] args) {
		//创建5根筷子对象
		Chopstick c1 = new Chopstick("1");
		Chopstick c2 = new Chopstick("2");
		Chopstick c3 = new Chopstick("3");
		Chopstick c4 = new Chopstick("4");
		Chopstick c5 = new Chopstick("5");
		new Philosopher("苏格拉底", c1, c2).start();
		new Philosopher("柏拉图", c2, c3).start();
		new Philosopher("亚里士多德", c3, c4).start();
		new Philosopher("赫拉克利特", c4, c5).start();
		new Philosopher("阿基米德", c5, c1).start();
	}
}

//哲学家
class Philosopher extends Thread {
	private Chopstick left;
	private Chopstick right;
	public Philosopher(String name, Chopstick left, Chopstick right) {
		super(name);		//给哲学家线程取名
		this.left = left;
		this.right = right;
	}
	
	@Override
	public void run() {
		while(true) {
			//尝试获得左手筷子
			if(left.tryLock()) {
				try {
					//尝试获得右手筷子
					if(right.tryLock()) {
						try {
							eat();
						} finally {
							right.unlock();
						} 
					}
				} finally {
					left.unlock();
				}
			}
		}
	}
	
	//吃饭
	public void eat() {
		LogUtils.log("Philosopher", "eating...");
		Sleeper.sleep(1);
	}
}

//筷子
class Chopstick extends ReentrantLock {
	String name;

	public Chopstick(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Chopstick [name=" + name + "]";
	}
}
